Add a xen boolean parameter 'x2apic'.
Add a xen boolean parameter 'x2apic_phys'(by default, we use logical
cluster mode).
Signed-off-by: Dexuan Cui <dexuan.cui@intel.com>
{
u32 lo, hi;
- if ( !iommu_supports_eim() )
- return;
+ if ( smp_processor_id() == 0 )
+ {
+ if ( !iommu_supports_eim() )
+ {
+ printk("x2APIC would not be enabled without EIM.\n");
+ return;
+ }
+
+ if ( apic_x2apic_phys.probe() )
+ genapic = &apic_x2apic_phys;
+ else if ( apic_x2apic_cluster.probe() )
+ genapic = &apic_x2apic_cluster;
+ else
+ {
+ printk("x2APIC would not be enabled due to x2apic=off.\n");
+ return;
+ }
+
+ x2apic_enabled = 1;
+ printk("Switched to APIC driver %s.\n", genapic->name);
+ }
+ else
+ {
+ BUG_ON(!x2apic_enabled); /* APs only enable x2apic when BSP did so. */
+ }
rdmsr(MSR_IA32_APICBASE, lo, hi);
if ( !(lo & MSR_IA32_APICBASE_EXTD) )
}
else
printk("x2APIC mode enabled by BIOS.\n");
-
- if ( !x2apic_enabled )
- {
- x2apic_enabled = 1;
- genapic = &apic_x2apic;
- printk(KERN_INFO "Switched to APIC driver %s.\n",
- genapic->name);
- }
}
void __init init_apic_mappings(void)
#include <xen/smp.h>
#include <asm/mach-default/mach_mpparse.h>
-__init int probe_x2apic(void)
+static int x2apic = 1;
+boolean_param("x2apic", x2apic);
+
+static int x2apic_phys = 0; /* By default we use logical cluster mode. */
+boolean_param("x2apic_phys", x2apic_phys);
+
+__init int probe_x2apic_phys(void)
+{
+ return x2apic && x2apic_phys && x2apic_is_available() &&
+ iommu_supports_eim();
+}
+
+__init int probe_x2apic_cluster(void)
{
- return x2apic_is_available();
+ return x2apic && !x2apic_phys && x2apic_is_available() &&
+ iommu_supports_eim();
}
-struct genapic apic_x2apic= {
- APIC_INIT("x2apic", probe_x2apic),
- GENAPIC_X2APIC
+struct genapic apic_x2apic_phys= {
+ APIC_INIT("x2apic_phys", probe_x2apic_phys),
+ GENAPIC_X2APIC_PHYS
+};
+
+struct genapic apic_x2apic_cluster= {
+ APIC_INIT("x2apic_cluster", probe_x2apic_cluster),
+ GENAPIC_X2APIC_CLUSTER
};
-void init_apic_ldr_x2apic(void)
+void init_apic_ldr_x2apic_phys(void)
{
- /* We only use physical delivery mode. */
return;
}
+void init_apic_ldr_x2apic_cluster(void)
+{
+ int cpu = smp_processor_id();
+ cpu_2_logical_apicid[cpu] = apic_read(APIC_LDR);
+}
void clustered_apic_check_x2apic(void)
{
- /* We only use physical delivery mode. */
return;
}
return cpumask_of_cpu(cpu);
}
-unsigned int cpu_mask_to_apicid_x2apic(cpumask_t cpumask)
+unsigned int cpu_mask_to_apicid_x2apic_phys(cpumask_t cpumask)
{
return cpu_physical_id(first_cpu(cpumask));
}
-void send_IPI_mask_x2apic(const cpumask_t *cpumask, int vector)
+unsigned int cpu_mask_to_apicid_x2apic_cluster(cpumask_t cpumask)
+{
+ return cpu_2_logical_apicid[first_cpu(cpumask)];
+}
+
+void send_IPI_mask_x2apic_phys(const cpumask_t *cpumask, int vector)
{
unsigned int cpu, cfg;
unsigned long flags;
local_irq_restore(flags);
}
+void send_IPI_mask_x2apic_cluster(const cpumask_t *cpumask, int vector)
+{
+ unsigned int cpu, cfg;
+ unsigned long flags;
+
+ mb(); /* see the comment in send_IPI_mask_x2apic_phys() */
+
+ local_irq_save(flags);
+
+ cfg = APIC_DM_FIXED | 0 /* no shorthand */ | APIC_DEST_LOGICAL | vector;
+ for_each_cpu_mask ( cpu, *cpumask )
+ if ( cpu != smp_processor_id() )
+ apic_wrmsr(APIC_ICR, cfg, cpu_2_logical_apicid[cpu]);
+
+ local_irq_restore(flags);
+}
APICFUNC(acpi_madt_oem_check)
extern struct genapic *genapic;
-extern struct genapic apic_x2apic;
+extern struct genapic apic_x2apic_phys;
+extern struct genapic apic_x2apic_cluster;
void init_apic_ldr_flat(void);
void clustered_apic_check_flat(void);
.send_IPI_mask = send_IPI_mask_flat, \
.send_IPI_self = send_IPI_self_flat
-void init_apic_ldr_x2apic(void);
+void init_apic_ldr_x2apic_phys(void);
+void init_apic_ldr_x2apic_cluster(void);
void clustered_apic_check_x2apic(void);
cpumask_t target_cpus_x2apic(void);
-unsigned int cpu_mask_to_apicid_x2apic(cpumask_t cpumask);
-void send_IPI_mask_x2apic(const cpumask_t *mask, int vector);
+unsigned int cpu_mask_to_apicid_x2apic_phys(cpumask_t cpumask);
+unsigned int cpu_mask_to_apicid_x2apic_cluster(cpumask_t cpumask);
+void send_IPI_mask_x2apic_phys(const cpumask_t *mask, int vector);
+void send_IPI_mask_x2apic_cluster(const cpumask_t *mask, int vector);
void send_IPI_self_x2apic(int vector);
cpumask_t vector_allocation_domain_x2apic(int cpu);
-#define GENAPIC_X2APIC \
+#define GENAPIC_X2APIC_PHYS \
.int_delivery_mode = dest_Fixed, \
.int_dest_mode = 0 /* physical delivery */, \
- .init_apic_ldr = init_apic_ldr_x2apic, \
+ .init_apic_ldr = init_apic_ldr_x2apic_phys, \
.clustered_apic_check = clustered_apic_check_x2apic, \
.target_cpus = target_cpus_x2apic, \
.vector_allocation_domain = vector_allocation_domain_x2apic, \
- .cpu_mask_to_apicid = cpu_mask_to_apicid_x2apic, \
- .send_IPI_mask = send_IPI_mask_x2apic, \
+ .cpu_mask_to_apicid = cpu_mask_to_apicid_x2apic_phys, \
+ .send_IPI_mask = send_IPI_mask_x2apic_phys, \
.send_IPI_self = send_IPI_self_x2apic
+#define GENAPIC_X2APIC_CLUSTER \
+ .int_delivery_mode = dest_LowestPrio, \
+ .int_dest_mode = 1 /* logical delivery */, \
+ .init_apic_ldr = init_apic_ldr_x2apic_cluster, \
+ .clustered_apic_check = clustered_apic_check_x2apic, \
+ .target_cpus = target_cpus_x2apic, \
+ .vector_allocation_domain = vector_allocation_domain_x2apic, \
+ .cpu_mask_to_apicid = cpu_mask_to_apicid_x2apic_cluster, \
+ .send_IPI_mask = send_IPI_mask_x2apic_cluster, \
+ .send_IPI_self = send_IPI_self_x2apic
+
void init_apic_ldr_phys(void);
void clustered_apic_check_phys(void);
cpumask_t target_cpus_phys(void);